Skip to content

Rejudge hardening: UTF-8-safe hooks, PowerShell coverage, guard/mem/workflow fixes, live demo - #8

Merged
blyatiful1 merged 1 commit into
masterfrom
claude/rejudge-hardening-windows-utf8
Jul 16, 2026
Merged

Rejudge hardening: UTF-8-safe hooks, PowerShell coverage, guard/mem/workflow fixes, live demo#8
blyatiful1 merged 1 commit into
masterfrom
claude/rejudge-hardening-windows-utf8

Conversation

@blyatiful1

@blyatiful1 blyatiful1 commented Jul 16, 2026

Copy link
Copy Markdown
Owner

An adversarial re-audit of the whole kit (multi-agent finder/verifier fleet, then a review of the resulting diff) surfaced defects the earlier self-review passes missed. This PR fixes the verified findings and adds a runnable hook demo.

Highlights

  • UTF-8-safe hooks (Windows). Every hook forces UTF-8 stdio + explicit file encodings. On Windows Python ≤3.14 (cp1252) a non-ASCII payload used to crash the read and fail the hook open — the claim-audit gate and compaction recovery were data-dependently inert on native Windows.
  • Destructive guard rebuilt. Scans every rm argument (rm -rf build/ / is caught), long-form + PowerShell spellings (Remove-Item -Recurse, without misreading -Force), Windows targets and <target>/* globs, quoted-heredoc bodies as literal data, and guards the PowerShell tool.
  • Installers were broken on stock Windows. install.ps1/doctor.ps1 now ship a UTF-8 BOM — Windows PowerShell 5.1 (the only PowerShell there) ParserError'd on the documented powershell -File install. Doctors gained event-level wiring, staleness, and wrong-interpreter checks; CI adds a PS 5.1 step.
  • fable-mem: atomic index upsert (concurrent session-ends can't corrupt it); token-boundary recall gate.
  • Workflows: three-way honesty (a dead finder is surfaced, never a falsely-clean report); big-task verifies commits landed; memory-gc capped + budget-guarded.
  • New tools/demo.py runs the real hooks against 5 failure modes in a sandbox (in CI via tests/test_demo.py).

Benchmark honesty

bench/RESULTS.md records a fresh 2026-07-16 A/B re-run: current stock Opus 4.8 now aces the task, so there is no measurable score delta (and n=3 is underpowered). The deterministic floor still fires — demo.py proves it — which is exactly the succession-doctrine outcome (keep the cheap floor, retire ceremony the model outgrew).

Verification

Suite: 226 passing, 23 skipped (the Windows baseline was failing 6); ~34 new regression tests; check-workflows.mjs green; demo.py 5/5.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a cross-platform live demo covering safety checks, recovery, and workflow safeguards.
    • Added broader Windows PowerShell support for hooks, installation, and diagnostics.
  • Bug Fixes
    • Improved destructive-command detection and loop alarms across Bash and PowerShell.
    • Prevented encoding issues with non-ASCII content, especially on Windows.
    • Improved memory search accuracy and concurrent updates.
    • Diagnostics now detect missing hook wiring while ignoring harmless line-ending differences.
  • Documentation
    • Updated Windows guidance, configuration notes, workflow behavior, limitations, and release information.
  • Tests
    • Expanded regression coverage for Windows, PowerShell, encoding, memory, demos, and safety protections.

…orkflow fixes, live demo

Adversarial re-audit of the whole kit (multi-agent finder/verifier fleet + a
review of the resulting diff) surfaced real defects the earlier self-review
passes missed. Fixes for the verified findings:

Hooks
- Every hook now forces UTF-8 stdio and opens transcripts/state with an explicit
  encoding. On Windows Python <=3.14 (cp1252 default) a non-ASCII payload used to
  crash the read and fail the hook OPEN — the claim-audit gate and compaction
  recovery were data-dependently inert on native Windows.
- Destructive guard: scans EVERY rm argument (`rm -rf build/ /` stray-space typo
  is caught), handles long-form GNU flags and the PowerShell deletion spellings
  (Remove-Item/ri/del, -Recurse + abbreviations) without misreading -Force,
  covers Windows catastrophic targets and the `<target>/*` glob form, treats
  quoted-delimiter heredoc bodies as literal data, and guards the PowerShell tool.
- Claim-audit gate: suite-claim negations ("not all tests pass yet") no longer
  false-block; counts PowerShell file-writes.
- Loop alarm: tracks the PowerShell tool; nudge wording is threshold-agnostic.

fable-mem
- Atomic index upsert (concurrent session-ends can't corrupt the index).
- Recall relevance gate is token-boundary, not substring; the keyword-count knob
  is split to FABLE_MEM_MIN_OVERLAP, decoupled from mem search's bm25 threshold.

Workflows
- Three-way honesty: a dead finder is surfaced in the returned result, never a
  falsely-clean report. big-task independently verifies each commit landed before
  a step counts green. memory-gc's judge fan-out is capped + budget-guarded.
  check-workflows strips strings/comments before the Date.now/Math.random scan.

Installers / doctors
- install.ps1 / doctor.ps1 ship a UTF-8 BOM: without it Windows PowerShell 5.1
  (the only PowerShell on stock Windows) ParserError'd on the documented
  `powershell -File` install. Both doctors gained event-level wiring checks (a
  partial merge dropping one block of a multi-event hook is now caught), a
  staleness check, and a wrong-interpreter check; CI adds a PS 5.1 step and the
  test suite falls back to powershell.exe when pwsh is absent.

Bench
- Windows-hermetic scoring (inherits os.environ, plugin autoload disabled);
  run.sh detects the venv layout; an honest 2026-07-16 A/B re-run is recorded in
  RESULTS.md (current stock Opus 4.8 now aces the task — no measurable delta,
  underpowered n; the deterministic floor still fires).

New
- tools/demo.py runs the real shipped hooks against five failure modes in a
  throwaway sandbox and asserts each fires; wired into CI via tests/test_demo.py.

Verifier agent now derives the changed surface itself via git diff instead of
trusting the caller's file list. Docs (README, CHANGELOG v2.1, SUCCESSION,
skills) updated to match. Suite: 226 passing, 23 skipped (the Windows baseline
was failing 6); ~34 new regression tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR hardens Windows PowerShell support, UTF-8 handling, destructive-command guards, memory indexing and recall, workflow verification, benchmark portability, doctor checks, and documentation. It adds a cross-platform demo and broad regression coverage for these behaviors.

Changes

Windows installation and enforcement

Layer / File(s) Summary
Windows installation and doctor verification
.github/workflows/*, install.ps1, tools/doctor.*, claude/settings/*, tests/test_windows_port.py, tests/test_install_doctor.py
Windows PowerShell 5.1 execution, BOM compatibility, PowerShell hook matchers, event-level wiring validation, tolerant drift checks, and CI coverage were added.
PowerShell enforcement and UTF-8 hook handling
claude/hooks/*, tests/test_destructive_guard.py, tests/test_loop_alarm.py, tests/test_stop_claim_audit.py, tests/test_compaction_hooks.py, tests/test_mem_*
Hooks now handle PowerShell events and explicit UTF-8 I/O; destructive recursive commands, heredocs, claim negations, loop alarms, and memory-hook behavior receive updated logic and regression tests.

Memory consistency and tooling

Layer / File(s) Summary
Memory consistency and token matching
claude/cli/mem.py, tests/test_mem_cli.py
Memory writes use atomic UPSERTs, while degraded search uses whole-token matching with concurrency and threshold tests.
Workflow, determinism, and benchmark integrity
claude/workflows/*, tools/check-workflows.mjs, bench/*, tests/test_bench.py
Workflow results expose incomplete coverage, commit checkpoints verify git state, skipped judge pairs become unverified, determinism scans ignore strings/comments, and benchmark execution supports Windows venvs with controlled pytest environments.
Cross-platform hook demonstration
tools/demo.py, tests/test_demo.py
A sandboxed demo exercises five hook scenarios and validates output, exit codes, listing behavior, and state isolation.

Documentation and guidance

Layer / File(s) Summary
Documentation and operational guidance
README.md, CHANGELOG.md, docs/*, claude/*.md, claude/skills/*, claude/settings/*
Documentation now describes Windows encoding, PowerShell coverage, loop thresholds, workflow reporting, effort-level semantics, and known enforcement limits.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant install.ps1
  participant settings.json
  participant doctor.ps1
  CI->>install.ps1: Execute with Windows PowerShell 5.1
  CI->>settings.json: Install Windows hook settings
  CI->>doctor.ps1: Validate files and event-level wiring
  doctor.ps1-->>CI: Return validation status
Loading

Possibly related PRs

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.01% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main hardening themes and the new live demo without being misleading.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/rejudge-hardening-windows-utf8

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.3)
claude/workflows/big-task.js

File contains syntax errors that prevent linting: Line 14: Illegal return statement outside of a function; Line 28: Illegal return statement outside of a function; Line 29: Illegal return statement outside of a function; Line 112: Illegal return statement outside of a function; Line 239: Illegal return statement outside of a function

claude/workflows/memory-gc.js

File contains syntax errors that prevent linting: Line 15: Illegal return statement outside of a function; Line 54: Illegal return statement outside of a function; Line 178: Illegal return statement outside of a function

claude/workflows/bug-hunt.js

File contains syntax errors that prevent linting: Line 129: Illegal return statement outside of a function

  • 1 others

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (1)
tests/test_loop_alarm.py (1)

214-222: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Complete the post-reset behavior assertions.

Assert that the successful write returns zero, then verify the third subsequent failure alarms. Otherwise, an erroneous alarm or permanently disabled counter can pass this test.

Proposed test extension
-    run_hook(tmp_path, "PowerShell", {"command": "Set-Content -Path x.py -Value 'fix'"})
+    reset = run_hook(tmp_path, "PowerShell",
+                     {"command": "Set-Content -Path x.py -Value 'fix'"})
+    assert reset.returncode == 0
     for _ in range(2):
         assert run_hook(tmp_path, "PowerShell", {"command": "python -m pytest -q"},
                         {}, event="PostToolUseFailure").returncode == 0
+    alarm = run_hook(tmp_path, "PowerShell", {"command": "python -m pytest -q"},
+                     {}, event="PostToolUseFailure")
+    assert alarm.returncode == 2
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_loop_alarm.py` around lines 214 - 222, Extend
test_powershell_write_success_resets_counts to assert the successful Set-Content
run returns zero, then add a third subsequent PostToolUseFailure invocation and
assert it alarms with the expected nonzero return code, covering both reset and
resumed counting behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bench/run.sh`:
- Around line 21-24: Update bench/run.sh to select the Windows
virtual-environment executable as Scripts/python.exe while preserving the POSIX
bin/python path. In tests/test_bench.py, update the fixture around the benchmark
setup to create Scripts/python.exe and assert that exact path is used.

In `@claude/agents/verifier.md`:
- Line 13: Update the repository discovery instructions in verifier.md to
include staged, unstaged, and untracked content: use git diff HEAD for tracked
changes, and explicitly inspect paths marked untracked by git status --short.
Ensure the verifier derives the complete changed surface from actual command
output rather than relying on the caller’s file list or git diff statistics.

In `@claude/hooks/posttool-loop-alarm.py`:
- Around line 62-68: Update the $null sink exclusion in the BASH_WRITE regex to
match PowerShell’s case-insensitive behavior, so redirects such as > $NULL are
not classified as writes. Apply the same case-insensitive change to the mirrored
claim-audit regex to keep both patterns synchronized.

In `@claude/hooks/pretool-destructive-guard.py`:
- Around line 92-111: Update _blank_quoted_heredocs to recognize heredoc
operators only when they are active shell syntax, excluding occurrences inside
ordinary single- or double-quoted strings while preserving valid heredoc
handling. Add a regression case covering an echoed quoted heredoc opener
followed by a destructive command, ensuring the command is not blanked and the
guard rejects it.
- Line 150: Update the _RM_INVOCATION regex to recognize the PowerShell rd and
rmdir aliases alongside the existing destructive commands, preserving
case-insensitive matching and argument capture. Add regression cases covering
both aliases, including the recursive rmdir form shown in the comment, and
verify they trigger the destructive-operation guard.

In `@claude/hooks/stop-claim-audit.py`:
- Line 47: Update the stop-claim audit regex and its synchronized loop-alarm
regex to match the PowerShell variable `$null` case-insensitively, while
preserving the existing redirect and device-path exclusions. Ensure mixed-case
forms such as `$NULL` and `$Null` are treated like `$null` and do not trigger a
modification.

In `@tests/test_demo.py`:
- Around line 34-52: Update test_demo_writes_no_state_to_the_users_real_dir to
isolate the fallback location by setting HOME and USERPROFILE to tmp_path in the
demo environment. Snapshot the synthetic ~/.claude/tmp/fable-protocol directory
recursively, including file contents and nested entries, before and after
run_demo, and assert the snapshots are identical.

In `@tests/test_destructive_guard.py`:
- Around line 333-337: Update the PowerShell destructive-command matcher
exercised by test_powershell_recurse_switch_syntax_blocks to parse the value of
the -Recurse switch, treating -Recurse:$false as non-recursive while continuing
to block enabled or abbreviated recursive forms. Add a regression assertion in
test_powershell_recurse_switch_syntax_blocks confirming the disabled form is
allowed.

In `@tests/test_install_doctor.py`:
- Around line 108-117: Update test_doctor_warns_on_windows_python_settings to
assert r.returncode == 0 after running DOCTOR, while retaining the existing bare
'python' diagnostic assertion.

In `@tests/test_small_tier.py`:
- Around line 89-92: Update the SKILL.md read in the test around the skill
assignment to pass encoding="utf-8" explicitly, matching the existing README
read and removing host-locale dependence.

In `@tools/check-workflows.mjs`:
- Around line 56-58: The stripStringsAndComments() scanner must recognize
JavaScript regex literals before interpreting // or /* as comments, so patterns
such as /[//]/ do not truncate the source before forbidden calls. Add
regex-literal handling with correct escaping and character-class support, or
replace the scanner with a real JavaScript lexer/parser, while preserving
existing string and comment stripping behavior.

In `@tools/doctor.ps1`:
- Around line 43-48: Update Test-AgentSame so it conditionally ignores only an
installer-injected frontmatter model pin in the installed copy: detect whether
the source content contains a model pin, and remove the installed copy’s
corresponding frontmatter pin only when the source has none. Preserve all source
pins and any model: text outside frontmatter, then compare the normalized
contents as before.

---

Nitpick comments:
In `@tests/test_loop_alarm.py`:
- Around line 214-222: Extend test_powershell_write_success_resets_counts to
assert the successful Set-Content run returns zero, then add a third subsequent
PostToolUseFailure invocation and assert it alarms with the expected nonzero
return code, covering both reset and resumed counting behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6faf3de1-d484-4adc-922a-3ecc7c5ddb42

📥 Commits

Reviewing files that changed from the base of the PR and between aae94cc and a58a9f7.

📒 Files selected for processing (47)
  • .github/workflows/ci.yml
  • CHANGELOG.md
  • README.md
  • bench/RESULTS.md
  • bench/run.sh
  • bench/score.py
  • claude/CLAUDE.md
  • claude/agents/verifier.md
  • claude/cli/mem.py
  • claude/hooks/posttool-loop-alarm.py
  • claude/hooks/posttool-test-weakening-alarm.py
  • claude/hooks/precompact-save-task.py
  • claude/hooks/pretool-destructive-guard.py
  • claude/hooks/pretool-mem-privacy-guard.py
  • claude/hooks/sessionend-mem-journal.py
  • claude/hooks/sessionstart-compact-recovery.py
  • claude/hooks/stop-claim-audit.py
  • claude/hooks/userpromptsubmit-mem-recall.py
  • claude/settings/settings-snippet-small.json
  • claude/settings/settings-snippet-windows-small.json
  • claude/settings/settings-snippet-windows.json
  • claude/skills/fable/SKILL.md
  • claude/skills/webdesign/SKILL.md
  • claude/workflows/big-task.js
  • claude/workflows/bug-hunt.js
  • claude/workflows/memory-gc.js
  • claude/workflows/paranoid-review.js
  • docs/SUCCESSION.md
  • install.ps1
  • tests/test_bench.py
  • tests/test_compaction_hooks.py
  • tests/test_demo.py
  • tests/test_destructive_guard.py
  • tests/test_docs.py
  • tests/test_install_doctor.py
  • tests/test_loop_alarm.py
  • tests/test_mem_cli.py
  • tests/test_mem_journal_hook.py
  • tests/test_mem_privacy_guard.py
  • tests/test_mem_recall_hook.py
  • tests/test_small_tier.py
  • tests/test_stop_claim_audit.py
  • tests/test_windows_port.py
  • tools/check-workflows.mjs
  • tools/demo.py
  • tools/doctor.ps1
  • tools/doctor.sh

Comment thread bench/run.sh
Comment on lines +21 to +24
VBIN=bin
[ -x "$INST/.venv/bin/python" ] || VBIN=Scripts
VENV_PY="$INST/.venv/$VBIN/python"
"$VENV_PY" -m pip -q install pytest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
# Run in native Windows Git Bash to confirm the actual venv executable layout.
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
python -m venv "$tmp/venv"
find "$tmp/venv" -maxdepth 2 -type f -iname 'python*' -print
test -x "$tmp/venv/Scripts/python.exe"

Repository: blyatiful1/fable-protocol

Length of output: 565


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n== bench/run.sh ==\n'
git ls-files bench/run.sh tests/test_bench.py
wc -l bench/run.sh tests/test_bench.py
printf '\n-- bench/run.sh (lines 1-120) --\n'
cat -n bench/run.sh | sed -n '1,120p'
printf '\n-- tests/test_bench.py (lines 120-190) --\n'
cat -n tests/test_bench.py | sed -n '120,190p'

printf '\n== Search for venv path handling ==\n'
rg -n 'Scripts/python|bin/python|python.exe|venv' bench tests -S

Repository: blyatiful1/fable-protocol

Length of output: 5312


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

sed -n '1,120p' bench/run.sh | cat -n
printf '\n----\n'
sed -n '130,180p' tests/test_bench.py | cat -n

Repository: blyatiful1/fable-protocol

Length of output: 3522


🌐 Web query:

MSYS Bash execute path without .exe suffix python.exe windows bash CreateProcess PATHEXT

💡 Result:

MSYS2 Bash does not automatically use the Windows PATHEXT environment variable to resolve executables without their file extensions [1][2]. While Windows native APIs, specifically CreateProcess, utilize PATHEXT to resolve commands when the executable extension is omitted, Bash operates as a POSIX-compliant shell that searches for files based on execution permissions within the Linux-style environment [2][3][4]. Key technical points regarding this behavior: 1. Windows API Behavior: The Windows CreateProcess function automatically appends.exe if no extension is provided and the file is not found, or iterates through PATHEXT if the executable is not in the current directory [3][4][5]. However, this logic is specific to Windows shells like cmd.exe and PowerShell, not the Bash shell itself [1][2]. 2. MSYS2/Bash Limitations: Bash requires an explicit path or filename (including the extension, such as.exe) to execute a file, unless a specific mechanism is in place to bridge this gap [6][7]. Some common Windows binaries may appear to run without extensions in MSYS2 only because they are provided as symbolic links or wrapper scripts within the MSYS2 /usr/bin directory, not because the shell is natively resolving them via PATHEXT [6]. 3. Workarounds: Users typically handle this by: - Creating aliases in.bashrc (e.g., alias python=python.exe) [6]. - Defining a command_not_found_handle function in their.bashrc that intercepts command-not-found errors, iterates through PATHEXT, and attempts to execute the command if a matching file is found [6][7]. - Creating shell scripts or wrappers in a directory already in the PATH that call the intended Windows executable [8][9]. In summary, because Bash is an independent environment, it does not share the same command resolution logic as Windows cmd.exe, and it remains the user's responsibility to handle extension-less execution through shell-level configuration [2][7].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n '\bScripts/python(\.exe)?\b|python\.exe\b|PATHEXT|msys|cygwin' -S .

Repository: blyatiful1/fable-protocol

Length of output: 377


🌐 Web query:

Cygwin Bash execute file without .exe suffix path /usr/bin/python.exe direct path no extension

💡 Result:

In the Cygwin environment, you typically do not need to include the.exe suffix to execute a binary, as Cygwin handles extensionless executable files automatically [1][2][3]. However, the ability to invoke these files depends on how the command is called and the environment from which it is executed [4][5][6]. Understanding Cygwin Execution Behavior: 1. Cygwin Shells (Bash, etc.): Within a Cygwin terminal, Bash is "Cygwin-aware." It recognizes executable files based on their POSIX permissions (chmod +x) or specific "magic" heuristics (such as the presence of #!, MZ, or: headers), regardless of whether they have a.exe extension [7][2][3]. If /usr/bin/python is in your PATH, running 'python' in a Cygwin shell should work without the.exe suffix [8][6]. 2. Windows CMD/PowerShell: Windows applications, including cmd.exe, do not share this Cygwin-specific awareness [4][5]. They generally require the literal.exe extension to identify and execute a binary correctly [4][9]. If you attempt to run /usr/bin/python (a symlink) from Windows CMD, it will likely fail because CMD does not understand the Cygwin symlink format or the expectation of implicit extension handling [4][9]. Troubleshooting and Workarounds: * Direct Path Execution: If you need to execute a file by its direct path from a Windows-native context (or a program that behaves like one), you must provide the full path including the.exe extension (e.g., C:\cygwin64\bin\python3.9.exe) [4][5]. * Creating Explicit Copies: If you require a specific command name to work across both environments (Cygwin and Windows CMD), a common workaround is to create a physical copy of the executable (or a hard link, if supported by the filesystem) with the required extension [1][4][9]. Avoid symlinks if you need to call the file from non-Cygwin programs, as these programs often fail to resolve them [4][6]. * PATH Configuration: Ensure that the directory containing the desired.exe is included in the Windows system PATH if you need to call it by name from outside the Cygwin environment [8][5][6]. For managing different versions of binaries like Python, it is recommended to use the 'alternatives' command within Cygwin to point 'python' to the desired version, which maintains the appropriate symlink structure within the Cygwin environment [8][4].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n 'windows-latest|Git Bash|MSYS|cygwin|Windows' .github bench tests README* -S

Repository: blyatiful1/fable-protocol

Length of output: 10985


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '\n-- bench/README.md --\n'
wc -l bench/README.md
cat -n bench/README.md | sed -n '1,140p'

printf '\n-- CI / benchmark mentions --\n'
rg -n 'bench/run.sh|benchmark arm|run one benchmark|bench/' README.md .github tests bench -S

Repository: blyatiful1/fable-protocol

Length of output: 7866


Handle the Windows venv executable name. bench/run.sh#L21-L24 still falls back to Scripts/python, but native Windows venvs expose Scripts/python.exe, so the benchmark stops before pip install pytest. tests/test_bench.py#L140-L160 only covers the POSIX bin/ case; make it use a Scripts/python.exe fixture and assert that exact path.

📍 Affects 2 files
  • bench/run.sh#L21-L24 (this comment)
  • tests/test_bench.py#L140-L160
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bench/run.sh` around lines 21 - 24, Update bench/run.sh to select the Windows
virtual-environment executable as Scripts/python.exe while preserving the POSIX
bin/python path. In tests/test_bench.py, update the fixture around the benchmark
setup to create Scripts/python.exe and assert that exact path is used.

Comment thread claude/agents/verifier.md

Try to REFUTE the claim:
1. Read the actual changed code not the caller's description of it.
1. Derive the changed surface yourself — `git status` + `git diff` (and `git diff --stat HEAD`), not the caller's file list. The caller's list is part of the claim, not ground truth: anything it omits is exactly where a false green hides. Then read the actual changed code, not the caller's description of it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include staged and untracked content when deriving the changed surface.

git diff omits staged changes, while git diff --stat HEAD provides only statistics; neither command reads untracked files. The verifier can therefore skip real changed code and return a false green. Use git diff HEAD for tracked staged/unstaged content and explicitly inspect paths reported as untracked by git status --short.

Suggested wording
-1. Derive the changed surface yourself — `git status` + `git diff` (and `git diff --stat HEAD`), not the caller's file list.
+1. Derive the changed surface yourself — inspect `git status --short`, read tracked changes with `git diff HEAD`, and inspect every untracked path reported by status; do not rely on the caller's file list.

Based on learnings, incomplete repository discovery is a false-green risk and must be verified from actual command output.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
1. Derive the changed surface yourself — `git status` + `git diff` (and `git diff --stat HEAD`), not the caller's file list. The caller's list is part of the claim, not ground truth: anything it omits is exactly where a false green hides. Then read the actual changed code, not the caller's description of it.
1. Derive the changed surface yourself — inspect `git status --short`, read tracked changes with `git diff HEAD`, and inspect every untracked path reported by status; do not rely on the caller's file list. The caller's list is part of the claim, not ground truth: anything it omits is where a false green hides. Then read the actual changed code, not the caller's description of it.
🧰 Tools
🪛 LanguageTool

[style] ~13-~13: Consider an alternative for the overused word “exactly”.
Context: ... not ground truth: anything it omits is exactly where a false green hides. Then read th...

(EXACTLY_PRECISELY)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@claude/agents/verifier.md` at line 13, Update the repository discovery
instructions in verifier.md to include staged, unstaged, and untracked content:
use git diff HEAD for tracked changes, and explicitly inspect paths marked
untracked by git status --short. Ensure the verifier derives the complete
changed surface from actual command output rather than relying on the caller’s
file list or git diff statistics.

Source: Learnings

Comment on lines 62 to 68
BASH_WRITE = re.compile(
r"(?<![0-9&])>>?\s*(?!&|/dev/(?:null|stdout|stderr)\b)\S"
r"(?<![0-9&])>>?\s*(?!&|\$null(?=[\s;|&]|$)|/dev/(?:null|stdout|stderr)\b)\S"
r"|(?:^|[|&;]\s*)(?:sed\s+(?:-\S+\s+)*-i|tee\s|patch\s|truncate\s"
r"|(?:git\s+(?:apply|mv|rm|checkout|restore|stash))|mv\s|cp\s|rm\s)"
r"|(?:git\s+(?:apply|mv|rm|checkout|restore|stash))|mv\s|cp\s|rm\s"
r"|(?i:set-content|add-content|out-file|new-item|move-item|copy-item"
r"|remove-item|rename-item)\b)"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match PowerShell’s case-insensitive $null sink.

A successful command > $NULL is currently classified as a file modification, clearing all loop counts despite making no change. Make this exemption case-insensitive and keep the mirrored claim-audit regex synchronized.

Proposed fix
-    r"(?<![0-9&])>>?\s*(?!&|\$null(?=[\s;|&]|$)|/dev/(?:null|stdout|stderr)\b)\S"
+    r"(?<![0-9&])>>?\s*(?!&|(?i:\$null)(?=[\s;|&]|$)|/dev/(?:null|stdout|stderr)\b)\S"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
BASH_WRITE = re.compile(
r"(?<![0-9&])>>?\s*(?!&|/dev/(?:null|stdout|stderr)\b)\S"
r"(?<![0-9&])>>?\s*(?!&|\$null(?=[\s;|&]|$)|/dev/(?:null|stdout|stderr)\b)\S"
r"|(?:^|[|&;]\s*)(?:sed\s+(?:-\S+\s+)*-i|tee\s|patch\s|truncate\s"
r"|(?:git\s+(?:apply|mv|rm|checkout|restore|stash))|mv\s|cp\s|rm\s)"
r"|(?:git\s+(?:apply|mv|rm|checkout|restore|stash))|mv\s|cp\s|rm\s"
r"|(?i:set-content|add-content|out-file|new-item|move-item|copy-item"
r"|remove-item|rename-item)\b)"
)
BASH_WRITE = re.compile(
r"(?<![0-9&])>>?\s*(?!&|(?i:\$null)(?=[\s;|&]|$)|/dev/(?:null|stdout|stderr)\b)\S"
r"|(?:^|[|&;]\s*)(?:sed\s+(?:-\S+\s+)*-i|tee\s|patch\s|truncate\s"
r"|(?:git\s+(?:apply|mv|rm|checkout|restore|stash))|mv\s|cp\s|rm\s"
r"|(?i:set-content|add-content|out-file|new-item|move-item|copy-item"
r"|remove-item|rename-item)\b)"
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@claude/hooks/posttool-loop-alarm.py` around lines 62 - 68, Update the $null
sink exclusion in the BASH_WRITE regex to match PowerShell’s case-insensitive
behavior, so redirects such as > $NULL are not classified as writes. Apply the
same case-insensitive change to the mirrored claim-audit regex to keep both
patterns synchronized.

Comment on lines +92 to +111
_HEREDOC_START = re.compile(r"<<-?\s*(['\"])([A-Za-z_]\w*)\1")


def _blank_quoted_heredocs(s):
"""Length- and newline-preserving blanking of QUOTED-delimiter heredoc bodies
(<<'EOF' ... EOF): those are pure literal data — no expansions execute inside —
so a test file or doc written through one must not trip the guard on strings it
merely CONTAINS (the kit's own test suite writes `rm -rf /` fixtures this way).
Unquoted-delimiter heredocs are left visible: `$(...)` executes inside them.
A missing terminator blanks to the end — which is also what the shell does."""
out = s
for m in list(_HEREDOC_START.finditer(s)):
delim = m.group(2)
line_end = out.find("\n", m.end())
if line_end == -1:
break
t = re.compile(r"\n[ \t]*" + re.escape(delim) + r"[ \t]*(?=\n|$)").search(out, line_end)
end = t.start() if t else len(out)
body = out[line_end + 1:end]
out = out[:line_end + 1] + re.sub(r"[^\n]", " ", body) + out[end:]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

Only blank active heredocs.

The matcher also accepts heredoc syntax inside ordinary quotes. For example, this command blanks the destructive second line even though Bash executes it:

echo "<<'EOF'"
rm -rf /
EOF

Track shell quoting when locating heredoc operators, and add this as a regression case. The current behavior fails the guard open.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 107-107: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.compile(r"\n[ \t]" + re.escape(delim) + r"[ \t](?=\n|$)")
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@claude/hooks/pretool-destructive-guard.py` around lines 92 - 111, Update
_blank_quoted_heredocs to recognize heredoc operators only when they are active
shell syntax, excluding occurrences inside ordinary single- or double-quoted
strings while preserving valid heredoc handling. Add a regression case covering
an echoed quoted heredoc opener followed by a destructive command, ensuring the
command is not blanked and the guard rejects it.

# token, so EVERY argument is a candidate target: `rm -rf build/ /` (the classic
# stray-space typo) is exactly as blocked as `rm -rf /`. -f is irrelevant: rm -r
# deletes without prompting in non-interactive shells.
_RM_INVOCATION = re.compile(r"\b(?:rm|ri|del|erase|remove-item)\s+(.*)", re.IGNORECASE)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '120,220p' claude/hooks/pretool-destructive-guard.py
printf '\n--- tests/search ---\n'
rg -n "rd|rmdir|remove-item|pretool-destructive-guard|RM_INVOCATION|destructive-guard" claude tests .

Repository: blyatiful1/fable-protocol

Length of output: 50382


🏁 Script executed:

sed -n '240,290p' tests/test_destructive_guard.py
printf '\n--- powershell alias search ---\n'
rg -n "rmdir|rd|remove-item|Remove-Item|PowerShell" tests/test_destructive_guard.py claude/hooks/pretool-destructive-guard.py

Repository: blyatiful1/fable-protocol

Length of output: 13129


🏁 Script executed:

sed -n '1,120p' claude/hooks/pretool-destructive-guard.py
printf '\n--- around rm parser ---\n'
sed -n '150,210p' claude/hooks/pretool-destructive-guard.py

Repository: blyatiful1/fable-protocol

Length of output: 8957


Cover the rd and rmdir PowerShell aliases. The PowerShell matcher already handles Remove-Item and ri, but not rd/rmdir, so rmdir -Recurse C:\ still bypasses the guard. Add regression cases for both aliases.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@claude/hooks/pretool-destructive-guard.py` at line 150, Update the
_RM_INVOCATION regex to recognize the PowerShell rd and rmdir aliases alongside
the existing destructive commands, preserving case-insensitive matching and
argument capture. Add regression cases covering both aliases, including the
recursive rmdir form shown in the comment, and verify they trigger the
destructive-operation guard.

Comment on lines +333 to +337
def test_powershell_recurse_switch_syntax_blocks(tmp_path):
repo = make_repo(tmp_path, dirty=False)
assert run_hook("Remove-Item -Recurse:$true C:\\", cwd=repo,
tool_name="PowerShell").returncode == 2
assert run_hook("Remove-Item -rec C:\\", cwd=repo, tool_name="PowerShell").returncode == 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover the disabled -Recurse:$false form.

The supplied matcher treats -Recurse:$false as recursive, so it will incorrectly block a non-recursive command. Parse the switch value and add an allowed regression case.

Suggested regression case
 def test_powershell_recurse_switch_syntax_blocks(tmp_path):
     repo = make_repo(tmp_path, dirty=False)
     assert run_hook("Remove-Item -Recurse:$true C:\\", cwd=repo,
                     tool_name="PowerShell").returncode == 2
     assert run_hook("Remove-Item -rec C:\\", cwd=repo, tool_name="PowerShell").returncode == 2
+    assert run_hook("Remove-Item -Recurse:$false C:\\", cwd=repo,
+                    tool_name="PowerShell").returncode == 0
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_powershell_recurse_switch_syntax_blocks(tmp_path):
repo = make_repo(tmp_path, dirty=False)
assert run_hook("Remove-Item -Recurse:$true C:\\", cwd=repo,
tool_name="PowerShell").returncode == 2
assert run_hook("Remove-Item -rec C:\\", cwd=repo, tool_name="PowerShell").returncode == 2
def test_powershell_recurse_switch_syntax_blocks(tmp_path):
repo = make_repo(tmp_path, dirty=False)
assert run_hook("Remove-Item -Recurse:$true C:\\", cwd=repo,
tool_name="PowerShell").returncode == 2
assert run_hook("Remove-Item -rec C:\\", cwd=repo, tool_name="PowerShell").returncode == 2
assert run_hook("Remove-Item -Recurse:$false C:\\", cwd=repo,
tool_name="PowerShell").returncode == 0
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_destructive_guard.py` around lines 333 - 337, Update the
PowerShell destructive-command matcher exercised by
test_powershell_recurse_switch_syntax_blocks to parse the value of the -Recurse
switch, treating -Recurse:$false as non-recursive while continuing to block
enabled or abbreviated recursive forms. Add a regression assertion in
test_powershell_recurse_switch_syntax_blocks confirming the disabled form is
allowed.

Comment on lines +108 to +117
def test_doctor_warns_on_windows_python_settings(tmp_path):
# Finding 5: a Windows snippet (bare `python`) merged on a POSIX box has hooks
# that never fire; doctor.sh must warn, mirroring doctor.ps1's python3 guard.
claude = tmp_path / "claude"
r = run(INSTALL, claude)
assert r.returncode == 0
win = json.loads((ROOT / "claude" / "settings" / "settings-snippet-windows.json").read_text())
(claude / "settings.json").write_text(json.dumps(win))
r = run(DOCTOR, claude, state_dir=tmp_path / "state")
assert "bare 'python'" in r.stdout, r.stdout

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert that this diagnostic remains non-fatal.

The test currently passes even if doctor.sh prints the warning and exits with failure.

Proposed test fix
     r = run(DOCTOR, claude, state_dir=tmp_path / "state")
+    assert r.returncode == 0, r.stdout + r.stderr
     assert "bare 'python'" in r.stdout, r.stdout
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_doctor_warns_on_windows_python_settings(tmp_path):
# Finding 5: a Windows snippet (bare `python`) merged on a POSIX box has hooks
# that never fire; doctor.sh must warn, mirroring doctor.ps1's python3 guard.
claude = tmp_path / "claude"
r = run(INSTALL, claude)
assert r.returncode == 0
win = json.loads((ROOT / "claude" / "settings" / "settings-snippet-windows.json").read_text())
(claude / "settings.json").write_text(json.dumps(win))
r = run(DOCTOR, claude, state_dir=tmp_path / "state")
assert "bare 'python'" in r.stdout, r.stdout
def test_doctor_warns_on_windows_python_settings(tmp_path):
# Finding 5: a Windows snippet (bare `python`) merged on a POSIX box has hooks
# that never fire; doctor.sh must warn, mirroring doctor.ps1's python3 guard.
claude = tmp_path / "claude"
r = run(INSTALL, claude)
assert r.returncode == 0
win = json.loads((ROOT / "claude" / "settings" / "settings-snippet-windows.json").read_text())
(claude / "settings.json").write_text(json.dumps(win))
r = run(DOCTOR, claude, state_dir=tmp_path / "state")
assert r.returncode == 0, r.stdout + r.stderr
assert "bare 'python'" in r.stdout, r.stdout
🧰 Tools
🪛 ast-grep (0.44.1)

[info] 114-114: use jsonify instead of json.dumps for JSON output
Context: json.dumps(win)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_install_doctor.py` around lines 108 - 117, Update
test_doctor_warns_on_windows_python_settings to assert r.returncode == 0 after
running DOCTOR, while retaining the existing bare 'python' diagnostic assertion.

Comment thread tests/test_small_tier.py
Comment on lines +89 to 92
readme = (REPO / "README.md").read_text(encoding="utf-8")
assert "/big-task" in readme
assert "ultracode" in readme, "README must document the ultracode composition story"
skill = (REPO / "claude/skills/orchestrate/SKILL.md").read_text()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the remaining documentation read UTF-8 explicit.

Line 89 is fixed, but Line 92 still calls read_text() without an encoding for claude/skills/orchestrate/SKILL.md. This keeps the test dependent on the host locale on Windows and can misdecode or fail on non-ASCII content.

Proposed fix
-    skill = (REPO / "claude/skills/orchestrate/SKILL.md").read_text()
+    skill = (REPO / "claude/skills/orchestrate/SKILL.md").read_text(encoding="utf-8")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
readme = (REPO / "README.md").read_text(encoding="utf-8")
assert "/big-task" in readme
assert "ultracode" in readme, "README must document the ultracode composition story"
skill = (REPO / "claude/skills/orchestrate/SKILL.md").read_text()
readme = (REPO / "README.md").read_text(encoding="utf-8")
assert "/big-task" in readme
assert "ultracode" in readme, "README must document the ultracode composition story"
skill = (REPO / "claude/skills/orchestrate/SKILL.md").read_text(encoding="utf-8")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_small_tier.py` around lines 89 - 92, Update the SKILL.md read in
the test around the skill assignment to pass encoding="utf-8" explicitly,
matching the existing README read and removing host-locale dependence.

Comment thread tools/check-workflows.mjs
Comment on lines +56 to +58
if (c === '/' && c2 === '/') { while (i < src.length && src[i] !== '\n') i++; continue }
if (c === '/' && c2 === '*') { i += 2; while (i < src.length && !(src[i] === '*' && src[i + 1] === '/')) i++; i++; continue }
if (c === "'" || c === '"') { i++; while (i < src.length && src[i] !== c) { if (src[i] === '\\') i++; i++ } out += ' '; continue }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the file first
ast-grep outline tools/check-workflows.mjs --view expanded || true

# Show the relevant section with line numbers
sed -n '1,180p' tools/check-workflows.mjs | cat -n

# Run a read-only probe that mimics the string/comment stripping logic
python3 - <<'PY'
src = "const slash = /[//]/; Date.now()"
out = ""
i = 0
while i < len(src):
    c = src[i]
    c2 = src[i+1] if i + 1 < len(src) else ""
    if c == '/' and c2 == '/':
        while i < len(src) and src[i] != '\n':
            i += 1
        continue
    if c == '/' and c2 == '*':
        i += 2
        while i < len(src) and not (src[i] == '*' and i + 1 < len(src) and src[i+1] == '/'):
            i += 1
        i += 1
        continue
    if c == "'" or c == '"':
        i += 1
        while i < len(src) and src[i] != c:
            if src[i] == '\\':
                i += 1
            i += 1
        out += ' '
        continue
    out += c
    i += 1

print("INPUT:", src)
print("OUTPUT:", out)
print("contains Date.now:", "Date.now" in out)
PY

Repository: blyatiful1/fable-protocol

Length of output: 5819


Handle regex literals before comment stripping.

stripStringsAndComments() treats // inside a regex literal as a line comment, so a line like const slash = /[//]/; Date.now() gets truncated before the forbidden call and bypasses the scan. Use a real JS lexer/parser, or add regex-literal handling before dropping comments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/check-workflows.mjs` around lines 56 - 58, The
stripStringsAndComments() scanner must recognize JavaScript regex literals
before interpreting // or /* as comments, so patterns such as /[//]/ do not
truncate the source before forbidden calls. Add regex-literal handling with
correct escaping and character-class support, or replace the scanner with a real
JavaScript lexer/parser, while preserving existing string and comment stripping
behavior.

Comment thread tools/doctor.ps1
Comment on lines +43 to +48
function Test-AgentSame([string]$A, [string]$B) {
if (-not (Test-Path $B -PathType Leaf)) { return $false }
$ca = (Get-NormContent $A) -split "`n" | Where-Object { $_ -notmatch '^model: ' }
$cb = (Get-NormContent $B) -split "`n" | Where-Object { $_ -notmatch '^model: ' }
return (($ca -join "`n") -eq ($cb -join "`n"))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Only ignore installer-injected frontmatter pins.

Removing every model: line from both files hides legitimate repository pin changes—and matching body text—from drift detection. Remove a frontmatter pin from the installed copy only when the source has no pin.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/doctor.ps1` around lines 43 - 48, Update Test-AgentSame so it
conditionally ignores only an installer-injected frontmatter model pin in the
installed copy: detect whether the source content contains a model pin, and
remove the installed copy’s corresponding frontmatter pin only when the source
has none. Preserve all source pins and any model: text outside frontmatter, then
compare the normalized contents as before.

@blyatiful1
blyatiful1 merged commit c58617a into master Jul 16, 2026
5 checks passed
@blyatiful1
blyatiful1 deleted the claude/rejudge-hardening-windows-utf8 branch July 16, 2026 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant